package com.example.excelutil.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Excel处理工具类
 */
@Slf4j
public class ExcelUtil {

    /**
     * 根据Excel文件输入流和列索引提取数据
     *
     * @param inputStream Excel文件输入流
     * @param columnIndex 要提取的列索引（从0开始）
     * @return 提取的数据列表
     * @throws IOException 如果读取文件出错
     */
    public static List<String> extractColumn(InputStream inputStream, int columnIndex) throws IOException {
        return extractColumn(inputStream, columnIndex, 0);
    }

    /**
     * 根据Excel文件输入流、列索引和工作表索引提取数据
     *
     * @param inputStream Excel文件输入流
     * @param columnIndex 要提取的列索引（从0开始）
     * @param sheetIndex  工作表索引（从0开始）
     * @return 提取的数据列表
     * @throws IOException 如果读取文件出错
     */
    public static List<String> extractColumn(InputStream inputStream, int columnIndex, int sheetIndex) throws IOException {
        List<String> columnData = new ArrayList<>();
        Workbook workbook = null;

        try {
            // 尝试以XLSX格式打开
            try {
                workbook = new XSSFWorkbook(inputStream);
            } catch (Exception e) {
                // 如果失败，重置输入流并尝试以XLS格式打开
                inputStream.reset();
                workbook = new HSSFWorkbook(inputStream);
            }

            Sheet sheet = workbook.getSheetAt(sheetIndex);
            int lastRowNum = sheet.getLastRowNum();

            for (int i = 0; i <= lastRowNum; i++) {
                Row row = sheet.getRow(i);
                if (row != null) {
                    Cell cell = row.getCell(columnIndex);
                    if (cell != null) {
                        columnData.add(getCellValueAsString(cell));
                    } else {
                        columnData.add(""); // 空单元格添加空字符串
                    }
                } else {
                    columnData.add(""); // 空行添加空字符串
                }
            }
        } finally {
            if (workbook != null) {
                workbook.close();
            }
        }

        return columnData;
    }

    /**
     * 根据Excel文件输入流和列名提取数据
     *
     * @param inputStream Excel文件输入流
     * @param columnName  要提取的列名
     * @return 提取的数据列表
     * @throws IOException 如果读取文件出错
     */
    public static List<String> extractColumnByName(InputStream inputStream, String columnName) throws IOException {
        return extractColumnByName(inputStream, columnName, 0);
    }

    /**
     * 根据Excel文件输入流、列名和工作表索引提取数据
     *
     * @param inputStream Excel文件输入流
     * @param columnName  要提取的列名
     * @param sheetIndex  工作表索引（从0开始）
     * @return 提取的数据列表
     * @throws IOException 如果读取文件出错
     */
    public static List<String> extractColumnByName(InputStream inputStream, String columnName, int sheetIndex) throws IOException {
        List<String> columnData = new ArrayList<>();
        Workbook workbook = null;

        try {
            // 尝试以XLSX格式打开
            try {
                workbook = new XSSFWorkbook(inputStream);
            } catch (Exception e) {
                // 如果失败，重置输入流并尝试以XLS格式打开
                inputStream.reset();
                workbook = new HSSFWorkbook(inputStream);
            }

            Sheet sheet = workbook.getSheetAt(sheetIndex);
            int lastRowNum = sheet.getLastRowNum();

            // 获取表头行
            Row headerRow = sheet.getRow(0);
            if (headerRow == null) {
                return columnData; // 如果没有表头行，返回空列表
            }

            // 查找列名对应的索引
            int columnIndex = -1;
            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null && columnName.equals(getCellValueAsString(cell))) {
                    columnIndex = i;
                    break;
                }
            }

            if (columnIndex == -1) {
                return columnData; // 如果找不到列名，返回空列表
            }

            // 提取数据（从第二行开始，跳过表头）
            for (int i = 1; i <= lastRowNum; i++) {
                Row row = sheet.getRow(i);
                if (row != null) {
                    Cell cell = row.getCell(columnIndex);
                    if (cell != null) {
                        columnData.add(getCellValueAsString(cell));
                    } else {
                        columnData.add(""); // 空单元格添加空字符串
                    }
                } else {
                    columnData.add(""); // 空行添加空字符串
                }
            }
        } finally {
            if (workbook != null) {
                workbook.close();
            }
        }

        return columnData;
    }

    /**
     * 获取单元格的值并转换为字符串
     *
     * @param cell 单元格
     * @return 单元格的字符串值
     */
    private static String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    // 避免数值显示为科学计数法
                    double value = cell.getNumericCellValue();
                    if (value == (long) value) {
                        return String.valueOf((long) value);
                    } else {
                        return String.valueOf(value);
                    }
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return String.valueOf(cell.getStringCellValue());
                } catch (Exception e) {
                    try {
                        return String.valueOf(cell.getNumericCellValue());
                    } catch (Exception ex) {
                        return cell.getCellFormula();
                    }
                }
            case BLANK:
                return "";
            default:
                return "";
        }
    }
}